﻿/*
 * ©2009-2010 XELF
 * http://xelf.info
 */

#if XNA || WINDOWS_PHONE
using Microsoft.Xna.Framework;
#endif

namespace XELF.Framework {
#if XNA || WINDOWS_PHONE
	public static partial class MatrixHelper {
#else
	public partial struct Matrix {
#endif
		/// <summary>
		/// 逆行列
		/// </summary>
		/// <param name="value"></param>
		/// <param name="result"></param>
		/// <returns></returns>
		public static float Invert(ref Matrix value, out Matrix result) {
			float t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11;
			Matrix s;
			Transpose(ref value, out s);

			// ペア
			t00 = s.M33 * s.M44;
			t01 = s.M34 * s.M43;
			t02 = s.M32 * s.M44;
			t03 = s.M34 * s.M42;
			t04 = s.M32 * s.M43;
			t05 = s.M33 * s.M42;
			t06 = s.M31 * s.M44;
			t07 = s.M34 * s.M41;
			t08 = s.M31 * s.M43;
			t09 = s.M33 * s.M41;
			t10 = s.M31 * s.M42;
			t11 = s.M32 * s.M41;

			// 余因子行列 前半8成分
			result.M11 = t00 * s.M22 + t03 * s.M23 + t04 * s.M24 - t01 * s.M22 - t02 * s.M23 - t05 * s.M24;
			result.M12 = t01 * s.M21 + t06 * s.M23 + t09 * s.M24 - t00 * s.M21 - t07 * s.M23 - t08 * s.M24;
			result.M13 = t02 * s.M21 + t07 * s.M22 + t10 * s.M24 - t03 * s.M21 - t06 * s.M22 - t11 * s.M24;
			result.M14 = t05 * s.M21 + t08 * s.M22 + t11 * s.M23 - t04 * s.M21 - t09 * s.M22 - t10 * s.M23;
			result.M21 = t01 * s.M12 + t02 * s.M13 + t05 * s.M14 - t00 * s.M12 - t03 * s.M13 - t04 * s.M14;
			result.M22 = t00 * s.M11 + t07 * s.M13 + t08 * s.M14 - t01 * s.M11 - t06 * s.M13 - t09 * s.M14;
			result.M23 = t03 * s.M11 + t06 * s.M12 + t11 * s.M14 - t02 * s.M11 - t07 * s.M12 - t10 * s.M14;
			result.M24 = t04 * s.M11 + t09 * s.M12 + t10 * s.M13 - t05 * s.M11 - t08 * s.M12 - t11 * s.M13;

			// ペア
			t00 = s.M13 * s.M24;
			t01 = s.M14 * s.M23;
			t02 = s.M12 * s.M24;
			t03 = s.M14 * s.M22;
			t04 = s.M12 * s.M23;
			t05 = s.M13 * s.M22;
			t06 = s.M11 * s.M24;
			t07 = s.M14 * s.M21;
			t08 = s.M11 * s.M23;
			t09 = s.M13 * s.M21;
			t10 = s.M11 * s.M22;
			t11 = s.M12 * s.M21;

			// 余因子行列 後半8成分
			result.M31 = t00 * s.M42 + t03 * s.M43 + t04 * s.M44 - t01 * s.M42 - t02 * s.M43 - t05 * s.M44;
			result.M32 = t01 * s.M41 + t06 * s.M43 + t09 * s.M44 - t00 * s.M41 - t07 * s.M43 - t08 * s.M44;
			result.M33 = t02 * s.M41 + t07 * s.M42 + t10 * s.M44 - t03 * s.M41 - t06 * s.M42 - t11 * s.M44;
			result.M34 = t05 * s.M41 + t08 * s.M42 + t11 * s.M43 - t04 * s.M41 - t09 * s.M42 - t10 * s.M43;
			result.M41 = t02 * s.M33 + t05 * s.M34 + t01 * s.M32 - t04 * s.M34 - t00 * s.M32 - t03 * s.M33;
			result.M42 = t08 * s.M34 + t00 * s.M31 + t07 * s.M33 - t06 * s.M33 - t09 * s.M34 - t01 * s.M31;
			result.M43 = t06 * s.M32 + t11 * s.M34 + t03 * s.M31 - t10 * s.M34 - t02 * s.M31 - t07 * s.M32;
			result.M44 = t10 * s.M33 + t04 * s.M31 + t09 * s.M32 - t08 * s.M32 - t11 * s.M33 - t05 * s.M31;

			var determinant = s.M11 * result.M11 + s.M12 * result.M12 + s.M13 * result.M13 + s.M14 * result.M14;

			Multiply(ref result, 1 / determinant, out result);

			return determinant;
		}

		/// <summary>
		/// 逆行列
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static Matrix Invert(Matrix value) {
			Matrix result;
			Invert(ref value, out result);
			return result;
		}
	}
}
